# -*- coding: utf-8 -*-
"""
流水线模块
负责协调整个视频生成流程
"""

from typing import Any, Dict, List, Optional, Callable
from abc import ABC, abstractmethod
from pathlib import Path
import json

from .config import Config
from .logger import LOGGER
from .exceptions import VideoGenerationError


class PipelineContext:
    """流水线上下文，存储中间状态和数据"""

    def __init__(self, config: Config, input_path: Path, output_dir: Path):
        self.config = config
        self.input_path = input_path
        self.output_dir = output_dir
        self.data: Dict[str, Any] = {}
        self.errors: List[str] = []
        self.warnings: List[str] = []

    def set(self, key: str, value: Any) -> None:
        """设置数据"""
        self.data[key] = value

    def get(self, key: str, default: Any = None) -> Any:
        """获取数据"""
        return self.data.get(key, default)

    def has_error(self) -> bool:
        """是否有错误"""
        return len(self.errors) > 0

    def add_error(self, error: str) -> None:
        """添加错误"""
        self.errors.append(error)
        LOGGER.error(error)

    def add_warning(self, warning: str) -> None:
        """添加警告"""
        self.warnings.append(warning)
        LOGGER.warning(warning)


class PipelineStep(ABC):
    """流水线步骤基类"""

    name: str
    description: str
    dependencies: List[str] = []

    def __init__(self, config: Config):
        self.config = config

    @abstractmethod
    def run(self, context: PipelineContext) -> bool:
        """
        执行步骤

        Args:
            context: 流水线上下文

        Returns:
            是否成功
        """
        pass

    def can_skip(self, context: PipelineContext) -> bool:
        """
        检查是否可以跳过

        Args:
            context: 流水线上下文

        Returns:
            是否可以跳过
        """
        return False

    def validate_dependencies(self, context: PipelineContext) -> bool:
        """
        验证依赖

        Args:
            context: 流水线上下文

        Returns:
            依赖是否满足
        """
        for dep in self.dependencies:
            if dep not in context.data:
                context.add_error(f"Missing dependency: {dep}")
                return False
        return True


class VideoPipeline:
    """视频生成流水线"""

    def __init__(self, config: Config, input_path: Path, output_dir: Path):
        self.config = config
        self.input_path = input_path
        self.output_dir = output_dir
        self.context = PipelineContext(config, input_path, output_dir)
        self.steps: List[PipelineStep] = []
        self.step_index: Dict[str, PipelineStep] = {}

    def add_step(self, step: PipelineStep) -> None:
        """
        添加步骤

        Args:
            step: 流水线步骤
        """
        self.steps.append(step)
        self.step_index[step.name] = step

    def run(self) -> bool:
        """
        运行流水线

        Returns:
            是否成功
        """
        LOGGER.info("Starting video generation pipeline")

        for step in self.steps:
            # 检查是否可以跳过
            if step.can_skip(self.context):
                LOGGER.info(f"Skipping step: {step.name}")
                continue

            # 验证依赖
            if not step.validate_dependencies(self.context):
                LOGGER.error(f"Step {step.name} failed due to missing dependencies")
                return False

            # 执行步骤
            LOGGER.info(f"Running step: {step.name} - {step.description}")
            try:
                success = step.run(self.context)
                if not success:
                    LOGGER.error(f"Step {step.name} failed")
                    return False
            except Exception as e:
                LOGGER.error(f"Step {step.name} raised exception: {e}")
                return False

        if self.context.has_error():
            LOGGER.error("Pipeline completed with errors")
            return False

        LOGGER.info("Pipeline completed successfully")
        return True

    def save_context(self, file_path: Path) -> None:
        """
        保存上下文到文件

        Args:
            file_path: 输出文件路径
        """
        context_data = {
            "config": self.config.to_dict(),
            "input_path": str(self.input_path),
            "output_dir": str(self.output_dir),
            "data": self.context.data,
            "errors": self.context.errors,
            "warnings": self.context.warnings,
        }

        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(context_data, f, ensure_ascii=False, indent=2)

    @classmethod
    def load_context(cls, file_path: Path) -> "VideoPipeline":
        """
        从文件加载上下文

        Args:
            file_path: 上下文文件路径

        Returns:
            流水线实例
        """
        with open(file_path, "r", encoding="utf-8") as f:
            context_data = json.load(f)

        config = Config(context_data["config"])
        input_path = Path(context_data["input_path"])
        output_dir = Path(context_data["output_dir"])

        pipeline = cls(config, input_path, output_dir)
        pipeline.context.data = context_data.get("data", {})
        pipeline.context.errors = context_data.get("errors", [])
        pipeline.context.warnings = context_data.get("warnings", [])

        return pipeline
